#include "AppLoad.h"

using namespace x2lib;

#pragma region IAppModule
IAppModule::IAppModule(IAppMaster* pAppMaster, const char* pszName, EMode eMode)
{
    m_pAppMaster = pAppMaster;
    m_isSuccLoad = false;
    m_isSuccUnLoad = false;
    m_pAppMaster->regist(this, pszName, eMode);
}
#pragma endregion


#pragma region IAppMaster

IAppMaster::IAppMaster()
{
    m_alreadyExecuted = false;
    m_nModules = 0;
    m_iCounter = 0;
}

void IAppMaster::notifyAppExec()
{
    m_alreadyExecuted = true;
    m_iCounter = 0;
    m_isSuccAll = true;

    m_vecThrId.emplace_back(Engine::Ignite(&m_lsTask2));

    for (auto& it: m_lsTask1)
    {
        int id = Engine::Ignite(&it);
        m_vecThrId.emplace_back(id);
    }

    for (auto& it: m_lsTask0)
    {
        report(it, true);
    }
}
void IAppMaster::notifyAppExit()
{
    m_iCounter = 0;
    m_isSuccAll = true;

    for (auto& it : m_lsTask0)
    {
        report(it, false);
    }

    for (auto& it : m_vecThrId)
    {
        Engine::Stall(it);
    }

    m_vecThrId.clear();
}
void IAppMaster::regist(IAppModule* pAppModule, const char* pszName, IAppModule::EMode eMode)
{
    if (m_alreadyExecuted) { return; }

    Module modul;
    modul.pModule = pAppModule;
    modul.strName = pszName;
    modul.eMode = eMode;
    if (eMode == IAppModule::EMode::Mode_Blocking)
    {
        m_lsTask0.emplace_back(modul);
    }
    else if (eMode == IAppModule::EMode::Mode_Individual)
    {
        m_lsTask1.emplace_back(modul);
    }
    else if (eMode == IAppModule::EMode::Mode_WorkQueue)
    {
        m_lsTask2.emplace_back(modul);
    }
    ++m_nModules;
}
void IAppMaster::report(Module& it, bool isOnLoad)
{
    it.Reset();
    it.isOnLoad = isOnLoad;
    onModuleReport(&it, m_isSuccAll, m_nModules == m_iCounter.load());

    if (isOnLoad)
    {
        it.isSucc = it.pModule->OnAppExec();
    }
    else
    {
        it.isSucc = it.pModule->OnAppExit();
    }

    it.isStept = true;
    it.pModule->m_isSuccLoad = it.isSucc;
    m_isSuccAll = (m_isSuccAll.load() && it.isSucc);

    ++m_iCounter;
    onModuleReport(&it, m_isSuccAll, m_nModules == m_iCounter.load());
}
void IAppMaster::onEngineExec(uint32_t id, void* vData)
{
    std::list<Module>* plsModule = (std::list<Module>*)(vData);

    if (plsModule == &m_lsTask1)
    {
        for (auto& it: m_lsTask1)
        {
            report(it, true);
        }
    }
    else
    {
        report(*(Module*)vData, true);
    }
}
void IAppMaster::onEngineExit(uint32_t id, void* vData)
{
    std::list<Module>* plsModule = (std::list<Module>*)(vData);

    if (plsModule == &m_lsTask1)
    {
        for (auto& it : m_lsTask1)
        {
            report(it, false);
        }
    }
    else
    {
        report(*(Module*)vData, false);
    }
}

#pragma endregion
